/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Jonhnny Weslley
 */
public class Ranking {

	static final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

	static final int PAGE_SIZE = 1000;
	static final int MAX = 78710;

	private Parser parser;
	private final Properties ranking;
	private final Map<Object, Object> alunos;
	private final List<String[]> results = new ArrayList<String[]>();
	private final List<Resource> resources = new ArrayList<Resource>();

	public Ranking(Map<Object, Object> alunos, Properties ranking) {
		this.alunos = alunos;
		this.ranking = ranking;
	}

	Ranking foreachResource() {
		for (int step = 0; step <= MAX; step += PAGE_SIZE) {
			resources.add(new Resource(step, parser));
		}
		return this;
	}

	Ranking useParser(Parser parser) {
		this.parser = parser;
		return this;
	}

	Ranking collectData() {
		for (int i = 0; i < resources.size() && alunos.size() > 0; i++) {
			resources.get(i).collectInto(results);
		}
		return this;
	}

	void saveTo(String filename) throws IOException {
		XMLBuilder builder = new XMLBuilder();
		builder.open("<ranking>\n");
		for (int i = 0; i < results.size(); i++) {
			String[] result = results.get(i);
			builder
			.open("<result>")
				.add("local", i + 1)
				.add("rank", result[0])
				.add("user-id", result[1])
				.add("user-name", result[2])
				.add("problems-solved", result[3])
				.add("problems-tried", result[4])
				.add("total-submissions", result[5])
				.add("progress", progress(result))
			.close("</result>");
		}

		builder.add("lastUpdated", dateFormat.format(new Date()));
		builder.close("\n</ranking>");
		PrintStream out = new PrintStream(new File(filename));
		out.print(builder.xml);
		out.close();
	}

	private Object progress(String[] result) {
		try {
			return (Integer.valueOf(ranking.getProperty(result[1])) - Integer.valueOf(result[0]));
		} catch (NumberFormatException e) {
			System.out.println(Arrays.toString(result));
			return 0;
		}
	}

	public static void main(String... args) throws IOException {
		String inputFilename = args.length > 0 ? args[0] : "alunos.properties";
		String rankingFilename = args.length > 1 ? args[1] : "alunos.rank.properties";
		String outputFilename = args.length > 2 ? args[2] : "ranking.xml";

		Properties properties = new Properties();
		properties.load(new FileInputStream(inputFilename));
		System.out.printf("Criando rank com %d alunos.\n", properties.size());
		Map<Object, Object> alunos = new ConcurrentHashMap<Object, Object>();
		alunos.putAll(properties);

		properties.clear();
		properties.load(new FileInputStream(rankingFilename));

		(new Ranking(alunos, properties))
			.useParser(new RegexBasedParser(alunos))
			.foreachResource()
			.collectData()
			.saveTo(outputFilename);
	}

}
